﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.Globalization;

namespace GPSTrakingListenerSerial
{
    public partial class MainForm : Form
    {
        // State object for reading client data asynchronously
        public class StateObject
        {
            // Client  socket.
            public Socket workSocket = null;
            // Size of receive buffer.
            public const int BufferSize = 1024;
            // Receive buffer.
            public byte[] buffer = new byte[BufferSize];
            // Received data string.
            public StringBuilder sb = new StringBuilder();
        }

        // Thread signal.
        public static ManualResetEvent allDone = new ManualResetEvent(false);
        public static bool Stop = false;
        public static int Port = 8886;

        public static DataTable dtLog = new DataTable();

        public MainForm()
        {
            InitializeComponent();

            dtLog.Columns.Add("GPSID");
            dtLog.Columns.Add("MessageDeviceColumn");
        }


        public static void AddRow(string GPSID, string MessageDevice)
        {
            DataRow row = dtLog.NewRow();
            row[0] = GPSID;
            row[1] = MessageDevice;

            dtLog.Rows.Add(row);
        }

        public static void StartListening()
        {
            IPEndPoint ep = new IPEndPoint(IPAddress.Any, Port);

            // Create a TCP/IP socket for listner.
            Socket listenerSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            // Bind the socket to the endpoint and wait for listen for incoming connections.
            try
            {
                listenerSock.Bind(ep);
                listenerSock.Listen(100);

                while (!Stop)
                {
                    try
                    {                                                                        
                        // Set the event to nonsignaled state.
                        allDone.Reset();
                        
                        // Start an asynchronous socket to listen for connections.                        
                        listenerSock.BeginAccept(new AsyncCallback(AcceptCallback), listenerSock);

                        // Wait until a connection is made before continuing.
                        allDone.WaitOne();
                    }
                    catch (Exception ex)
                    {
                        
                    }

                }

            }
            catch (Exception ex)
            {
                
            }
        }

        public static void AcceptCallback(IAsyncResult ar)
        {
            // Signal the main thread to continue.
            allDone.Set();

            // Get the socket that handles the client request.
            Socket listener = (Socket)ar.AsyncState;
            Socket handler = listener.EndAccept(ar);

            // Create the state object.
            StateObject MessageDevice = new StateObject();
            MessageDevice.workSocket = handler;

            handler.BeginReceive(MessageDevice.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), MessageDevice);

            
        }

        public static void ReadCallback(IAsyncResult ar)
        {
            // Retrieve the state object and the handler socket
            // from the asynchronous state object.
            StateObject MessageDevice = (StateObject)ar.AsyncState;
            Socket handler = MessageDevice.workSocket;

            // Read data from the client socket.
            int bytesRead = handler.EndReceive(ar);

            if (bytesRead > 0)
            {

                if (MessageDevice.buffer[2] == 0xB1 || MessageDevice.buffer[2] == 0xB0)
                {
                    

                    //EnterpriseLibraryLoggingCustom.Log.Info("Connection accepted from " + handler.RemoteEndPoint);
                    //EnterpriseLibraryLoggingCustom.Log.Info("Recieved From GPSID-" + GPSiTracProtocol.GPSiTracProtocol900C.GetImei(MessageDevice.buffer));

                    string MessageDeviceHex = GPSiTracProtocol.GPSiTracProtocol900C.ConvertToHexString(MessageDevice.buffer, bytesRead);
                    //EnterpriseLibraryLoggingCustom.Log.Info("Message Device: " + MessageDeviceHex);

                    AddRow(GPSiTracProtocol.GPSiTracProtocol900C.GetImei().ToString(), MessageDeviceHex);

                    // Not all data received. Get more.
                    handler.BeginReceive(MessageDevice.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), MessageDevice);

                }
                else
                {
                   

                    // Send command pendients



                    // Message Send
                    byte[] MessageSend = new byte[0];
                    switch (MessageDevice.buffer[2])
                    {
                        case 0x80:

                        byte[] GPSID = GPSiTracProtocol.GPSiTracProtocol900C.GetGPSID();
                        MessageSend = GPSiTracProtocol.GPSiTracProtocol900C.SendOK();

                        break;

                    }

                    //string MessageDeviceHex = ConvertToHexString(MessageDevice.buffer, bytesRead);
                    //EnterpriseLibraryLoggingCustom.Log.Info("Message Device: " + MessageDeviceHex);

                    if (MessageSend.Length > 0)
                        Send(handler, MessageSend);
                }

            }

        }

        private static void Send(Socket handler, byte[] MessageSend)
        {
            // Begin sending the data to the remote device.
            //EnterpriseLibraryLoggingCustom.Log.Info("Message Send: " + ConvertToHexString(MessageSend, -1));
            handler.BeginSend(MessageSend, 0, MessageSend.Length, 0, new AsyncCallback(SendCallback), handler);
        }

        private static void SendCallback(IAsyncResult ar)
        {
            try
            {
                // Retrieve the socket from the state object.
                Socket handler = (Socket)ar.AsyncState;

                // Complete sending the data to the remote device.
                int bytesSent = handler.EndSend(ar);
                //EnterpriseLibraryLoggingCustom.Log.Info("Disconnected... Sent " + bytesSent.ToString() + " bytes to gps device.");
                handler.Shutdown(SocketShutdown.Both);
                handler.Close();

            }
            catch (Exception ex)
            {
                //EnterpriseLibraryLoggingCustom.Log.Error("Error..... " + ex.StackTrace);
            }
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            Stop = false;
            timer1.Enabled = true;
            btnStart.Enabled = false;
            btnStop.Enabled = true;

            Thread TCPListenerThread = new Thread(StartListening);
            TCPListenerThread.Start();   

        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            Stop = true;
            timer1.Enabled = false;

            btnStart.Enabled = true;            
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            dataGridView1.DataSource = dtLog;
        }

        private void MessageDevice_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                //0x29, 0x29, 0x80, 0x00, 0x28, 0x37, 0x18, 0x86, 0x54, 0x12, 0x07, 0x29, 0x18, 0x03, 0x43, 0x01, 0x00, 0x33, 0x35, 0x88, 0x42, 0x64, 0x76, 0x00, 0x00, 0x01, 0x89, 0xFF, 0xFF, 0x00, 0x00, 0x82, 0xFC, 0x00, 0x00, 0x00, 0x0F, 0x64, 0x0A, 0x10, 0x00, 0x00, 0x34, 0x5D, 0x0D                

                string[] _str = txtMessageDevice.Text.Trim().Replace("0x", "").Replace("-",",").Replace(" ",",").Split(',');//.Replace("0x", "").Replace(",", "");

                byte[] _Byte = _str.Select(s => Byte.Parse(s,
                                           NumberStyles.HexNumber,
                                           CultureInfo.InvariantCulture)
                          ).ToArray();



                GPSiTracProtocol.GPSiTracProtocol900C.MessageDevice = _Byte;
                GPSiTracProtocol.GPSiTracProtocol900C.GPSDeviceID = GPSiTracProtocol.GPSiTracProtocol900C.GetGPSID();


                lblGPSID.Text = GPSiTracProtocol.GPSiTracProtocol900C.GetImei().ToString();

                chkACC.Checked = GPSiTracProtocol.GPSiTracProtocol900C.IsACCOn();
                chkInputShock.Checked = GPSiTracProtocol.GPSiTracProtocol900C.IsInputShockActivated();
                chkInputDoor.Checked = GPSiTracProtocol.GPSiTracProtocol900C.IsInputDoorOpen();
                chkMainPowerOn.Checked = GPSiTracProtocol.GPSiTracProtocol900C.IsMainPowerOn();
                chkSosAlarm.Checked = GPSiTracProtocol.GPSiTracProtocol900C.IsEmergencySOSAlarmActivated();
                chkOverSpeed.Checked = GPSiTracProtocol.GPSiTracProtocol900C.IsOverSpeedAlarmActivated();
                chkCircuitCutting.Checked = GPSiTracProtocol.GPSiTracProtocol900C.IsCircuitCuttingActivated();
                checkBox1.Checked = GPSiTracProtocol.GPSiTracProtocol900C.IsGeoferenceExitAlarmActivated();
                checkBox2.Checked = GPSiTracProtocol.GPSiTracProtocol900C.IsGeoferenceEnterAlarmActivated();

                txtLocation.Text = GPSiTracProtocol.GPSiTracProtocol900C.GetCoordinate(GPSiTracProtocol.GPSiTracProtocol900C.MessageCoordinate.Latitude).ToString() + "," +
                    GPSiTracProtocol.GPSiTracProtocol900C.GetCoordinate(GPSiTracProtocol.GPSiTracProtocol900C.MessageCoordinate.Longitude).ToString();
                txtSpeed.Text = GPSiTracProtocol.GPSiTracProtocol900C.GetSpeed().ToString();
                                  

            }
        }

        private void txtMessageDevice_MouseClick(object sender, MouseEventArgs e)
        {
            txtMessageDevice.Clear();
        }
    }
}
